#ifndef __SERVER_MGR_H__
#define __SERVER_MGR_H__

#include <map>
#include <memory>
#include <mutex>
#include <thread>

#include <boost/asio.hpp>

#include <google/protobuf/message.h>

#include "server_cfg.h"

class IManager;
class IServer;
class ISubServerMgr;

union MessageID;

enum ServerType : uint16_t
{
    eNone = 0,
    eClient = 1,      ///< 客户端
    eLoginServer = 2, ///< 登录服务器
    eLoginGate = 3,   ///< 登录网关服务器
    eServerGate = 4,      ///< 游戏网关
    eGameServer = 5,      ///< 游戏逻辑服务器
    eDbServer = 6,        ///< 数据服务器
    eServerCenter,    ///< 中心服务器
    eServerName,      ///< 名字服务器
};

enum ManagerType
{
    eModule,         ///< 模块管理器
    eSession,        ///< 连接会话管理器
    eCmdModule,      ///< 命令管理器
    eGmModule,       ///< GM管理器
    eConfig,         ///< 配置管理器
};

class ServerMgr
{
public:
    ServerMgr& operator=(const ServerMgr&) = delete;
    ServerMgr(const ServerMgr&) = delete;

    /**
     * @desc 初始化
     * @auth Qiwei.Gu
     * @date 2015-03-21 16:19:14
     */
    bool init(std::shared_ptr<ISubServerMgr> subSrvMgr);

    /**
     * @desc 全局单例实现，通过它拿到其他所有资源
     * @auth Qiwei.Gu
     * @date 2015-03-21 12:23:48
     */
    static ServerMgr& get()
    {
        static ServerMgr mgr;
        return mgr;
    }

    boost::asio::io_service& getIOS() { return ios_; }

    void run();

    /**
     * @desc 添加管理器类
     * @auth Qiwei.Gu
     * @date 2015-03-21 12:26:30
     */
    bool addMgr(ManagerType type, std::shared_ptr<IManager> mgr);

    /**
     * @desc 查询管理器类
     * @auth Qiwei.Gu
     * @date 2015-03-21 12:57:13
     */
    std::shared_ptr<IManager> getMgr(ManagerType type);

    /**
     * @desc 查询管理器模版类
     * @auth Qiwei.Gu
     * @date 2015-03-21 12:57:13
     */
    template<typename _T>
    std::shared_ptr<_T> getMgr(ManagerType type)
    {
        auto mgr = getMgr(type);
        return mgr ? std::dynamic_pointer_cast<_T>(mgr) : std::shared_ptr<_T>();
    }

    /**
     * @desc 重新加载所有配置
     * @auth Qiwei.Gu
     * @date 2015-04-06 17:40:33
     */
    bool reloadConfig();

    /**
     * @desc 返回服务器配置
     * @auth Qiwei.Gu
     * @date 2015-04-19 00:08:03
     */
    const std::shared_ptr<ServerCfg>& getServerCfg() const { return servCfg_; }

    /**
     * @desc 添加服务器
     * @auth Qiwei.Gu
     * @date 2015-03-21 15:24:05
     */
    void addServer(ServerType serverType, const std::shared_ptr<IServer>& server);

    /**
     * @desc 向特定服务器发送消息
     * @auth Qiwei.Gu
     * @date 2015-03-21 15:24:21
     */
    void sendToServers(ServerType serverType, MessageID msgID, uint32_t sessionID,
                       const google::protobuf::Message& msg);

    /**
     * @desc 设置具体的服务管理类
     * @auth Qiwei.Gu
     * @date 2015-03-21 16:04:09
     */
    void setSubServ(const std::shared_ptr<ISubServerMgr>& speci) { subSrvMgr_ = speci; }
    std::shared_ptr<ISubServerMgr> getSubServ() { return subSrvMgr_; }
    template<typename _T>
    std::shared_ptr<_T> getSubServ() { return std::dynamic_pointer_cast<_T>(getSubServ()); }

    /**
     * @desc 生成随机数，左闭右闭，[0, 99]
     * @param min 最小值
     * @param max 最大值
     * @auth Qiwei.Gu
     * @date 2015-05-04 15:58:37
     */
    uint16_t getRandInt(uint16_t min = 0, uint16_t max = 99);

private:
    ServerMgr() {}

    /**
     * @desc 初始化随机数生成器
     */
    void initRand();

private:
    std::map<ManagerType, std::shared_ptr<IManager>> mgrs_;         // 各种管理器
    std::multimap<ServerType, std::shared_ptr<IServer>> servers_;   // 服务器
    boost::asio::io_service ios_;                                   // asio io server
    std::mutex mutex_;
    std::shared_ptr<ISubServerMgr> subSrvMgr_;            // 具体的服务管理类
    std::vector<std::thread> iosThreads_;
    std::shared_ptr<ServerCfg> servCfg_;

    std::mt19937 randEngine_;
};

#endif // __SERVER_MGR_H__
